package jpm.main;

import static jpm.common.AssertUtils.ensureNotNull;

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

import jpm.common.JPMException;
import jpm.position.Cache;
import jpm.position.PositionKey;
import jpm.position.PositionValue;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// command line arguments
		// First argument: multipleThreads
		// possible values: true or false.
		// default: true
		// true indicates multiple threads should be used while updating
		// positions
		//
		// Second argument: shuffle
		// possible values: true or false.
		// default: true.
		// true indicates the trades should be randomly shuffled before updating
		// positions

		try {

			boolean multipleThreads = false;
			boolean shuffle = false;

			if (args.length > 0) {
				if (args[0].toUpperCase().equals("TRUE"))
					multipleThreads = true;
			}

			if (args.length > 1) {
				if (args[1].toUpperCase().equals("TRUE"))
					shuffle = true;
			}

			final String INPUT_FILE = "input.csv";

			System.out.println("Cmd line parameters: multipleThreads [" + multipleThreads
					+ "], shuffle [" + shuffle + "]\n--------------------");

			TradeSimulator.playEventsFromFile(INPUT_FILE, "|",
					multipleThreads, shuffle, System.out);
						
			Map<PositionKey, PositionValue> positionCache = Cache
					.getPositionCache();
			
			printCache(positionCache);
			
		} catch (Throwable ex) {
			if (ex instanceof JPMException) {
				JPMException jpmException = (JPMException) ex;
				System.out.println("Caught JPMException \nError type: "
						+ jpmException.getErrorCode()
						+ "\nUser friendly message: "
						+ jpmException.getUserFriendlyMessage());
			} else
				System.out.println("Caught unhandled exception");

			System.out.println("\nStack trace:");
			ex.printStackTrace();
		}
	}
	
	private static void printCache(Map<PositionKey, PositionValue> positionCache) {
		ensureNotNull(positionCache, "positionCache is not null");
			
		System.out.println("----------------------------------");
		
		// sort 
		TreeMap<PositionKey, PositionValue> sortedPositionCache = new TreeMap<PositionKey, PositionValue>(
				new Comparator<PositionKey>() {

					@Override
					public int compare(PositionKey arg0,
							PositionKey arg1) {

						if (arg0.getAccountNo().equals(arg1.getAccountNo()))
							return arg0.getSecurity().compareTo(
									arg1.getSecurity());

						return arg0.getAccountNo().compareTo(
								arg1.getAccountNo());
					}
				});
		sortedPositionCache.putAll(positionCache);

		System.out.println("\nPosition cache (num entries: " + positionCache.size() + ")");
		System.out.println("Account|Instrument|Quantity|Trades");
		for (PositionKey key : sortedPositionCache.keySet()) {
			PositionValue value = sortedPositionCache
					.get(key);
			System.out.println(asString(key) + asString(value));
		}
	}
	
	private static String asString(PositionKey key) {
		ensureNotNull(key, "positionKey is null");
		return key.getAccountNo() + "|" + key.getSecurity() + "|";
	}
	
	private static String asString(PositionValue value) {
		ensureNotNull(value, "positionValue is null");
		
		StringBuilder builder = new StringBuilder();
		
		builder.append(value.getQuantity() + "|");
		
		int i = 0;
		int size = value.getTradeIds().size();
		for (Integer tradeId : value.getTradeIds()) {
			builder.append(tradeId);
			
			i++;
			if (i != size)
				builder.append(",");
		}
		
		return builder.toString();
	}
}
